package smtpserver

import (
	"net"
	"time"

	"github.com/cloudwego/netpoll"
)

// NetpollConnAdapter 将 netpoll.Connection 适配为 Connection 接口
type NetpollConnAdapter struct {
	conn netpoll.Connection
}

// NewNetpollConnAdapter 创建新的 netpoll 连接适配器
func NewNetpollConnAdapter(conn netpoll.Connection) *NetpollConnAdapter {
	return &NetpollConnAdapter{conn: conn}
}

// Read 实现 Connection 接口的 Read 方法
func (a *NetpollConnAdapter) Read(b []byte) (int, error) {
	if a.conn == nil {
		return 0, net.ErrClosed
	}
	reader := a.conn.Reader()
	if reader == nil {
		return 0, net.ErrClosed
	}
	data, err := reader.ReadBinary(len(b))
	if err != nil {
		return 0, err
	}
	if len(data) == 0 {
		return 0, nil
	}
	copy(b, data)
	return len(data), nil
}

// Write 实现 Connection 接口的 Write 方法
func (a *NetpollConnAdapter) Write(b []byte) (int, error) {
	if a.conn == nil {
		return 0, net.ErrClosed
	}
	writer := a.conn.Writer()
	if writer == nil {
		return 0, net.ErrClosed
	}
	n, err := writer.WriteBinary(b)
	if err != nil {
		return 0, err
	}
	return n, writer.Flush()
}

// Close 实现 Connection 接口的 Close 方法
func (a *NetpollConnAdapter) Close() error {
	return a.conn.Close()
}

// RemoteAddr 实现 Connection 接口的 RemoteAddr 方法
func (a *NetpollConnAdapter) RemoteAddr() net.Addr {
	return a.conn.RemoteAddr()
}

// LocalAddr 实现 Connection 接口的 LocalAddr 方法
func (a *NetpollConnAdapter) LocalAddr() net.Addr {
	return a.conn.LocalAddr()
}

// SetReadDeadline 实现 Connection 接口的 SetReadDeadline 方法
func (a *NetpollConnAdapter) SetReadDeadline(t time.Time) error {
	return a.conn.SetReadTimeout(time.Until(t))
}

// SetWriteDeadline 实现 Connection 接口的 SetWriteDeadline 方法
func (a *NetpollConnAdapter) SetWriteDeadline(t time.Time) error {
	return a.conn.SetWriteTimeout(time.Until(t))
}

// SetDeadline 实现 Connection 接口的 SetDeadline 方法
func (a *NetpollConnAdapter) SetDeadline(t time.Time) error {
	return a.conn.SetDeadline(t)
}

// NetpollReaderAdapter 将 netpoll.Reader 适配为 io.Reader
type NetpollReaderAdapter struct {
	reader netpoll.Reader
}

func NewNetpollReaderAdapter(reader netpoll.Reader) *NetpollReaderAdapter {
	return &NetpollReaderAdapter{reader: reader}
}

func (a *NetpollReaderAdapter) Read(p []byte) (n int, err error) {
	data, err := a.reader.ReadBinary(len(p))
	if err != nil {
		return 0, err
	}
	n = copy(p, data)
	return n, nil
}
